import React, { ChangeEvent, FormEvent, useRef, useState } from "react";
import "./input.scss";

/**
 * @param type 类型
 * @param placeholder 输入框占位文本
 * @param disabled 是否禁用
 * @param readonly 是否只读
 * @param maxlength 同原生 maxlength 属性
 * @param showWordCount 是否显示统计字数, 只在 type 为 'text' 的时候生效
 * @param size 输入框尺寸 'default' | 'large' | 'small'
 * @param clearable 是否可以清空
 * @param autofocus 原生属性，自动获取焦点
 * @param max 原生 max 属性，设置最大值
 * @param min 原生属性，设置最小值
 * @param name 等价于原生 input name 属性
 * @param show-password 是否显示密码
 * @param id 输入框id
 * @param defaultValue 默认值
 * @param onBlur 当选择器的输入框失去焦点时触发
 * @param onFocus 当选择器的输入框获得焦点时触发
 * @param onChange 仅当 modelValue 改变时，当输入框失去焦点或用户按Enter时触发
 * @param onInput 在 Input 值改变时触发
 * @param clear 在点击由 clearable 属性生成的清空按钮时触发
 * @param prefix 前置元素
 * @param suffix 后置元素
 * @param value 输入框的值
 */
interface Props {
    type?: 'text' | 'password' | 'number',
    placeholder?: string,
    disabled?: boolean,
    readonly?: boolean,
    maxlength?: number,
    showWordCount?: boolean,
    clearable?: boolean,
    size?: 'default' | 'large' | 'small',
    autofocus?: boolean,
    max?: number,
    min?: number,
    name?: string,
    showPassword?: boolean,
    prefixIcon?: React.ReactNode,
    suffixIcon?: React.ReactNode,
    id?: string,
    defaultValue?: string | number,
    onBlur?: () => void,
    onFocus?: () => void,
    onChange?: (event: ChangeEvent<HTMLInputElement>) => void,
    onInput?: (event: FormEvent<HTMLInputElement>) => void,
    clear?: () => void,
    prefix?: React.ReactNode,
    suffix?: React.ReactNode,
    className?: string,
    style?: React.CSSProperties,
    value?: string | number
}

const Input = ({
    type = "text",
    placeholder,
    disabled = false,
    readonly = false,
    maxlength,
    showWordCount = false,
    clearable = false,
    size = "default",
    autofocus = false,
    max,
    min,
    name,
    showPassword = false,
    prefixIcon,
    suffixIcon,
    id,
    defaultValue = "",
    onBlur = () => { },
    onFocus = () => { },
    onChange = () => { },
    onInput = () => { },
    clear = () => { },
    prefix,
    suffix,
    className,
    style,
    value
}: Props) => {
    const [value1, setValue] = useState<string | number>(defaultValue)

    // 边框颜色
    const [borderColor, setBorderColor] = useState<string>("")

    // 输入框元素ref
    const peInput = useRef<HTMLInputElement>(null)

    // 获取焦点
    const inputFocus = () => {
        if (!disabled) {
            peInput.current?.focus();
        }
    }

    const [typePassword, setTypePassword] = useState<string>("password")

    return (
        <div className={["pe-input", className, `pe-input-${size}`].join(" ").trim()}
            style={{ '--pe-input-border-color': borderColor, '--pe-input-hover-border-color': disabled ? 'var(--pe-input-border-color)' : '', ...style } as React.CSSProperties}>
            {
                prefix || prefix === 0 ? <div className="pe-input-slot pe-input-prefix-slot">{prefix}</div> : null
            }
            <div className="pe-input-wrapper" onClick={(e) => {
                e.stopPropagation()
                inputFocus()
            }}>
                {
                    prefixIcon || prefixIcon === 0 ? <span className="pe-input-icon">{prefixIcon}</span> : null
                }
                <input ref={peInput} className="pe-input-inner" id={id} value={value}
                    type={type === 'password' ? typePassword : type} disabled={disabled} readOnly={readonly} placeholder={placeholder}
                    maxLength={maxlength} autoFocus={autofocus} max={max} min={min} name={name}
                    onBlur={() => {
                        setBorderColor("var(--pe-color-border)")
                        onBlur()
                    }}
                    onFocus={() => {
                        setBorderColor("var(--pe-color-primary)")
                        onFocus()
                    }}
                    onChange={(e) => {
                        onChange(e)
                    }}
                    onInput={(e) => {
                        let value2: string | number = (e.target as HTMLInputElement).value
                        if(type === 'number') {
                            value2 = Number((e.target as HTMLInputElement).value)
                        }
                        setValue(value2)
                        onInput(e)
                    }} />
                {
                    showWordCount ? <span className="pe-input-count">{String(value1).length}{Number(maxlength) >= 0 ? `/${maxlength}` : ''}</span> : null
                }
                {
                    showPassword && type === 'password' && String(value1).length > 0 ? (
                        <span className="pe-input-icon">
                            {
                                typePassword === 'text' ? (
                                    <i className="pe-icon show-password" onClick={() => {
                                        setTypePassword("password")
                                    }}>
                                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                                            <path fill="currentColor"
                                                d="M512 160c320 0 512 352 512 352S832 864 512 864 0 512 0 512s192-352 512-352m0 64c-225.28 0-384.128 208.064-436.8 288 52.608 79.872 211.456 288 436.8 288 225.28 0 384.128-208.064 436.8-288-52.608-79.872-211.456-288-436.8-288zm0 64a224 224 0 1 1 0 448 224 224 0 0 1 0-448m0 64a160.192 160.192 0 0 0-160 160c0 88.192 71.744 160 160 160s160-71.808 160-160-71.744-160-160-160">
                                            </path>
                                        </svg>
                                    </i>
                                ) : (
                                    <i className="pe-icon show-password" onClick={() => {
                                        setTypePassword("text")
                                    }}>
                                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                                            <path fill="currentColor"
                                                d="M876.8 156.8c0-9.6-3.2-16-9.6-22.4-6.4-6.4-12.8-9.6-22.4-9.6-9.6 0-16 3.2-22.4 9.6L736 220.8c-64-32-137.6-51.2-224-60.8-160 16-288 73.6-377.6 176C44.8 438.4 0 496 0 512s48 73.6 134.4 176c22.4 25.6 44.8 48 73.6 67.2l-86.4 89.6c-6.4 6.4-9.6 12.8-9.6 22.4 0 9.6 3.2 16 9.6 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l704-710.4c3.2-6.4 6.4-12.8 6.4-22.4Zm-646.4 528c-76.8-70.4-128-128-153.6-172.8 28.8-48 80-105.6 153.6-172.8C304 272 400 230.4 512 224c64 3.2 124.8 19.2 176 44.8l-54.4 54.4C598.4 300.8 560 288 512 288c-64 0-115.2 22.4-160 64s-64 96-64 160c0 48 12.8 89.6 35.2 124.8L256 707.2c-9.6-6.4-19.2-16-25.6-22.4Zm140.8-96c-12.8-22.4-19.2-48-19.2-76.8 0-44.8 16-83.2 48-112 32-28.8 67.2-48 112-48 28.8 0 54.4 6.4 73.6 19.2zM889.599 336c-12.8-16-28.8-28.8-41.6-41.6l-48 48c73.6 67.2 124.8 124.8 150.4 169.6-28.8 48-80 105.6-153.6 172.8-73.6 67.2-172.8 108.8-284.8 115.2-51.2-3.2-99.2-12.8-140.8-28.8l-48 48c57.6 22.4 118.4 38.4 188.8 44.8 160-16 288-73.6 377.6-176C979.199 585.6 1024 528 1024 512s-48.001-73.6-134.401-176Z">
                                            </path>
                                            <path fill="currentColor"
                                                d="M511.998 672c-12.8 0-25.6-3.2-38.4-6.4l-51.2 51.2c28.8 12.8 57.6 19.2 89.6 19.2 64 0 115.2-22.4 160-64 41.6-41.6 64-96 64-160 0-32-6.4-64-19.2-89.6l-51.2 51.2c3.2 12.8 6.4 25.6 6.4 38.4 0 44.8-16 83.2-48 112-32 28.8-67.2 48-112 48Z">
                                            </path>
                                        </svg>
                                    </i>
                                )
                            }
                        </span>
                    ) : null
                }
                {
                    clearable && String(value1).length > 0 ? (
                        <span className="pe-input-icon" style={{ marginRight: 5 }}>
                            <i className="pe-icon pe-input-clearable" onClick={() => {
                                setValue("")
                                peInput.current?.focus();
                                clear()
                            }}>
                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" data-v-ea893728="">
                                    <path fill="currentColor"
                                        d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896m0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336z">
                                    </path>
                                </svg>
                            </i>
                        </span>
                    ) : null
                }
                {
                    suffixIcon ? <span className="pe-input-icon">{suffixIcon}</span> : null
                }
            </div>
            {
                suffix ? <div className="pe-input-slot pe-input-suffix-slot">{suffix}</div> : null
            }
            {
                disabled ? <div className="pe-disabled"></div> : null
            }
        </div >
    )
}

export default Input